package demo.db.redis;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;

import demo.db.redis.jedis.JedisDemo;
import io.lettuce.core.KeyValue;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisFuture;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
import io.lettuce.core.api.sync.RedisCommands;
import io.lettuce.core.cluster.RedisClusterClient;
import io.lettuce.core.cluster.api.StatefulRedisClusterConnection;
import io.lettuce.core.cluster.api.sync.RedisAdvancedClusterCommands;

/**
 * Lettuce使用Netty作为底层通信框架
 * <p>
 * 基于Netty的连接实例（StatefulRedisConnection），可以在多个线程间并发访问，且线程安全，满足多线程环境下的并发访问，同时它是可伸缩的设计，一个连接实例不够的情况也可以按需增加连接实例。
 */
public class LettuceDemo {

    private static Logger logger = LoggerFactory.getLogger(LettuceDemo.class);

    @Test
    public void demo() throws ExecutionException, InterruptedException {
        RedisClient redisClient = buildRedisClient1();
        StatefulRedisConnection<String, String> connection = redisClient.connect();
        String key = "ma.param.config";

        RedisCommands<String, String> commands = connection.sync();
        System.err.println(commands.get(key));

        RedisAsyncCommands<String, String> asyncCommands = connection.async();
        RedisFuture<String> rs = asyncCommands.get(key);
        rs.thenAccept(System.out::println);
        while (!rs.isDone()) {
            System.out.println(rs.get());
        }
        connection.close();
        redisClient.shutdown();
    }

    /**
     * 集群
     */
    @Test
    public void demoLettuceClusterClient() {
        ArrayList<RedisURI> list = new ArrayList<>();
        list.add(RedisURI.create("redis://172.16.0.140:6379"));
        list.add(RedisURI.create("redis://172.16.0.142:6379"));
        list.add(RedisURI.create("redis://172.16.0.146:6379"));
        RedisClusterClient client = RedisClusterClient.create(list);
        // RedisClusterClient client = RedisClusterClient.create("redis://192.168.37.128:7000");
        StatefulRedisClusterConnection<String, String> connect = client.connect();

        /* 同步执行的命令 */
        RedisAdvancedClusterCommands<String, String> commands = connect.sync();
        String str = commands.get("test2");
        System.out.println(str);

        /* 异步执行的命令 */
        // RedisAdvancedClusterAsyncCommands<String, String> commands= connect.async();
        // RedisFuture<String> future = commands.get("test2");
        // try {
        // String str = future.get();
        // System.out.println(str);
        // } catch (InterruptedException e) {
        // e.printStackTrace();
        // } catch (ExecutionException e) {
        // e.printStackTrace();
        // }

        connect.close();
        client.shutdown();
    }

    /**
     * 单机同步
     */
    @Test
    public void demoSync() {
        RedisClient redisClient = buildRedisClient();
        try (StatefulRedisConnection<String, String> connect = redisClient.connect();) {
            /* 同步执行的命令 */
            RedisCommands<String, String> commands = connect.sync();
            String key = "ma.param.config";
            String value = commands.get(key);
            logger.info(value);
            String str2 = commands.get("ma.approver.online.time.1540");
            logger.info(str2);
        }
        redisClient.shutdown();
    }

    /**
     * 单机异步
     */
    @Test
    public void demoAsync() {
        RedisClient redisClient = buildRedisClient();
        try (StatefulRedisConnection<String, String> connect = redisClient.connect();) {
            /* 同步执行的命令 */
            String key = "ma.param.config";

            /* 异步执行的命令 */
            RedisAsyncCommands<String, String> commands = connect.async();
            RedisFuture<String> future = commands.get(key);
            try {
                String str = future.get();
                logger.info(str);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        redisClient.shutdown();
    }

    public static RedisClient buildRedisClient() {
        RedisURI redisUri = RedisURI.create("redis://172.16.0.140:6379");
        redisUri.setPassword("sider");
        redisUri.setDatabase(13);
        redisUri.setTimeout(Duration.ofSeconds(10));
        RedisClient redisClient = RedisClient.create(redisUri);
        return redisClient;
    }

    public static RedisClient buildRedisClient1() {
        RedisURI redisUri = RedisURI.builder().withHost("172.16.0.140").withPort(6379).withPassword("sider")
                .withDatabase(13).build();
        RedisClient redisClient = RedisClient.create(redisUri);
        return redisClient;
    }

    public static RedisClient buildRedisClient2() {
        RedisURI redisUri = RedisURI.Builder.redis("172.16.0.140").withPort(6379).withPassword("sider").withDatabase(13)
                .build();
        RedisClient redisClient = RedisClient.create(redisUri);
        return redisClient;
    }

    public static RedisClient buildRedisClient3() {
        RedisURI redisUri = new RedisURI(JedisDemo.host, JedisDemo.port, Duration.ofSeconds(10));
        redisUri.setPassword(JedisDemo.auth);
        redisUri.setDatabase(13);
        RedisClient redisClient = RedisClient.create(redisUri);
        return redisClient;
    }

    @Test
    public void testDemo() {
        RedisClient client = buildRedisClient3();
        try (StatefulRedisConnection<String, String> connect = client.connect();) {
            /* 同步执行的命令 */
            RedisCommands<String, String> commands = connect.sync();
            String value = commands.get("1");
            System.out.println(value);
            List<KeyValue<String, String>> mGetResult = commands.mget("1", "2", "3", "4", "5");
            System.out.println(mGetResult);
        }

    }
}
